import uuid
from dataclasses import dataclass
from typing import Any

import pytest
from sqlalchemy import insert
from sqlalchemy.ext.asyncio import AsyncSession

from recruit.adapter.database.gateway import ResumeAboutUsGateway
from recruit.adapter.database.models import Resume, ResumeAboutUs
from tests.adapter.gateway.utils import (
    delete_user,
    check_attr_model,
    check_get_one, get_resume,
)
from .fixtures.resume import ResumeTest


@dataclass
class ResumeAboutUsTest:
    id: uuid.uuid4()
    resume_id: uuid.uuid4()
    about_us: str


async def _create_resume_about_us(
        session: AsyncSession,
        data: dict[str, Any]
) -> ResumeAboutUsTest:
    stmt = insert(ResumeAboutUs).values(**data).returning(ResumeAboutUs)
    resume_about_us = (await session.execute(stmt)).scalar_one()
    resume_about_us = ResumeAboutUsTest(
        id=resume_about_us.id,
        resume_id=resume_about_us.resume_id,
        about_us=resume_about_us.about_us
    )
    await session.commit()
    return resume_about_us


async def _check_resume(
        session: AsyncSession,
        data: ResumeAboutUsTest
) -> None:
    resume_about_us = await get_resume(session, ResumeAboutUs, data.id)
    assert isinstance(resume_about_us, ResumeAboutUs)
    check_get_one(
        resume_about_us,
        data,
        ('id', 'resume_id', 'about_us')
    )


async def test_create(
        db_session: AsyncSession,
        get_resume_about_us: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_about_us_gateway = ResumeAboutUsGateway(db_session)
    get_resume_about_us['resume_id'] = create_resume.id
    resume_about_us = await resume_about_us_gateway.create(
        **get_resume_about_us
    )
    assert isinstance(resume_about_us.resume, Resume)
    check_attr_model(resume_about_us, get_resume_about_us)
    await db_session.commit()
    await delete_user(db_session, create_resume.user_id)


@pytest.mark.parametrize(
    'keys', [
        ('id', 'resume_id', 'about_us')
    ]
)
async def test_get_one(
        keys: tuple[str, ...],
        db_session: AsyncSession,
        get_resume_about_us: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_about_us_gateway = ResumeAboutUsGateway(db_session)
    get_resume_about_us['resume_id'] = create_resume.id
    created_resume_about_us = await _create_resume_about_us(
        db_session,
        get_resume_about_us
    )
    for key, value in get_resume_about_us.items():
        resume_about_us = await resume_about_us_gateway.get_one(**{key: value})
        assert resume_about_us is not None
        check_get_one(resume_about_us, created_resume_about_us, keys)
    await delete_user(db_session, create_resume.user_id)


@pytest.mark.parametrize(
    'data, keys', [(
            {
                'about_us': 'test'
            },
            ('id', 'resume_id')
    )]
)
async def test_update(
        data: dict[str, Any],
        keys: tuple[str, ...],
        db_session: AsyncSession,
        get_resume_about_us: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_about_us_gateway = ResumeAboutUsGateway(db_session)
    get_resume_about_us['resume_id'] = create_resume.id
    created_resume_about_us = await _create_resume_about_us(
        db_session,
        get_resume_about_us
    )
    resume_about_us = await resume_about_us_gateway.update(
        created_resume_about_us.resume_id, **data
    )
    check_get_one(resume_about_us, created_resume_about_us, keys)
    check_attr_model(resume_about_us, data)
    await db_session.commit()
    created_resume_about_us.about_us = data['about_us']
    await _check_resume(db_session, created_resume_about_us)
    await delete_user(db_session, create_resume.user_id)


async def test_check_resume(
        db_session: AsyncSession,
        get_resume_about_us: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_about_us_gateway = ResumeAboutUsGateway(db_session)
    get_resume_about_us['resume_id'] = create_resume.id
    created_resume_about_us = await _create_resume_about_us(
        db_session,
        get_resume_about_us
    )
    val = await resume_about_us_gateway.check_resume(
        created_resume_about_us.resume_id
    )
    assert val
    await delete_user(db_session, create_resume.user_id)
    val = await resume_about_us_gateway.check_resume(
        created_resume_about_us.resume_id
    )
    assert not val


async def test_delete(
        db_session: AsyncSession,
        get_resume_about_us: dict[str, Any],
        create_resume: ResumeTest
) -> None:
    resume_about_us_gateway = ResumeAboutUsGateway(db_session)
    get_resume_about_us['resume_id'] = create_resume.id
    created_resume_about_us = await _create_resume_about_us(
        db_session,
        get_resume_about_us
    )
    await resume_about_us_gateway.delete(created_resume_about_us.resume_id)
    await db_session.commit()
    await delete_user(db_session, create_resume.user_id)
    resume_about_us = await get_resume(
        db_session,
        ResumeAboutUs,
        created_resume_about_us.id
    )
    assert resume_about_us is None
